package com.wennn.top.common.util;

import com.wennn.top.common.annotation.ReflectField;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.core.ReflectUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @description: 工具类
 * @author: wennn
 * @date: 7/7/20
 */
@Slf4j
public class BeanUtils {

    /**
     * 对象复制
     * @param src       源对象
     * @param target    目标对象（通过@ReflectField注解指定源对象哪个字段与此对应）
     * @param <T>
     * @return
     */
    public static<T> T copyByReflectField(Object src, Class<T> target){

        Object targetInstance = ReflectUtils.newInstance(target);
        List<Field> allFields = getAllFields(target, new ArrayList<>());

        for (Field f:allFields){
            boolean accessibleSrc = f.isAccessible();
            f.setAccessible(true);
            ReflectField valProp = f.getDeclaredAnnotation(ReflectField.class);
            String name = f.getName();
            if(null != valProp && valProp.name() != ""){
                name = valProp.name();
            }
            try {
                Field declaredField = src.getClass().getDeclaredField(name);
                boolean accessibleTarget = declaredField.isAccessible();
                declaredField.setAccessible(true);
                Object val = declaredField.get(src);
                f.set(targetInstance,val);
                declaredField.setAccessible(accessibleTarget);
                f.setAccessible(accessibleSrc);
            } catch (NoSuchFieldException|IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        return (T) targetInstance;
    }

    /**
     * 对象copy
     * @param src
     * @param target
     * @param ignoreProperties
     * @param <T>
     * @return
     */
    public static<T> T copy(Object src,Class<T> target,String... ignoreProperties){
        Object o = ReflectUtils.newInstance(target);
        org.springframework.beans.BeanUtils.copyProperties(src,o,ignoreProperties);
        return (T) o;
    }

    /**
     * 对象copy
     * @param src
     * @param target
     * @param <T>
     * @return
     */
    public static<T> T copy(Object src,Class<T> target){
        return copy(src,target,null);
    }


    /**
     * 获取对象所有属性
     * @param clazz
     * @param fields
     * @return
     */
    public static List<Field> getAllFields(Class clazz, List<Field> fields) {
        if (clazz != null) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            getAllFields(clazz.getSuperclass(), fields);
        }
        return fields;
    }
}
